//
// Created by 11510 on 2024/6/19.
//
#include <iostream>

using namespace std;

class A {
public:
    virtual void a() { cout << "A::a()" << endl; }

    virtual void b() { cout << "A::b()" << endl; }

    virtual void c() { cout << "A::c()" << endl; }
};

class B {
public:
    virtual void a() { cout << "B::a()" << endl; }

    virtual void b() { cout << "B::b()" << endl; }

    void c() { cout << "B::c()" << endl; }

    void d() { cout << "B::d()" << endl; }
};

/**
 * 我的理解：两个父类有同名方法，按继承的顺序，覆盖第一个，虚表中后一个类的虚函数调用的是同一个函数
 */
class C : public A, public B {
public:
    virtual void a() { cout << "C::a()" << endl; }

    /* 这也是虚函数 */
    void c() { cout << "C::c()" << endl; }

    void d() { cout << "C::d()" << endl; }
};


class D : public C {
public:
    /* 虚函数 */
    void c() { cout << "D::c()" << endl; }
};


void test0() {
    C c;
    c.a();/* 隐藏，没有走虚表 */
//    c.b();/* 成员名访问冲突二义性 */
    c.c();/* 隐藏 */
    c.d();/* 隐藏 */

    cout << endl;
    A* pa = &c;
    pa->a();
    pa->b();
    pa->c();
//    pa->d();

    cout << endl;
    B* pb = &c;
    pb->a();
    pb->b();
    pb->c();
    pb->d();

    cout << endl;
    C * pc = &c;
    pc->a();
//    pc->b();/* 成员名访问冲突二义性 */
    pc->c();
    pc->d();

    cout << endl;
    D d;
    d.a();
    C *pc2 = &d;
    pc2->a();/* 动态多态 */

    cout << endl;
    d.c();
    pc2->c();   /* 动态多态 */

}
void test1(){
    /**
     * 没有指针直接调用，这里都是隐藏
     */
    C c;
    c.a();
//    c.b();/* 二义性 */
    c.B::c();
    c.c();
    c.d();
    cout << endl;

    A* pa = &c;
    pa->a();/* 覆盖 */
    pa->b();/* 调A的虚表的b() */
    pa->c();/* 覆盖 */
//    pa->d();    /* 父类指针只能调用父类有的方法 */
    cout << endl;

    /*
     * C::a()
     * B::b()
     * C::c()
     * C::d()
     */
    B* pb = &c;
    pb->a();/* 调B的虚表的a(),但是在a()中goto A的虚表的a() */
    pb->b();/* 调B的虚表的b() */
    pb->c();/* B的c()不是虚函数，直接调B的c() */
    pb->d();/* B的d()不是虚函数，直接调B的d() */
    cout << endl;

    /**
     * C::a()
     * C::c()
     * C::d()
     */
    C * pc = &c;
    pc->a();/* 访问虚表，但没有触发动态多态 */
//    pc->b(); /* 二义性 */
    pc->c();/* 访问虚表，但没有触发动态多态 */
    pc->d();/* 隐藏 */
    cout << endl;

    D d;
    d.a();
    cout << endl;

    C *pc2 = &d;
    pc2->a(); /* 访问虚表，动态多态 */
    cout << endl;

    d.c();  /* 未访问虚表，隐藏 */
    pc2->c();   /* 访问虚表，动态多态 */

    B* pb2 = &d;
    pb2->c();
}

int main(void) {

    test1();
    return 0;
}